﻿using Domain.Event;
using Domain.IRepositorys;
using Domain.Model;
using DTO;
using Infrastructure.Error;
using Infrastructure.UniOfWorkBase;
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Security.Claims;
using System.IdentityModel.Tokens.Jwt;
using Microsoft.IdentityModel.Logging;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using AutoMapper;
using Domain.Services;
using Domain.Types;
using Microsoft.Extensions.Configuration;
using OtherLib.TenXun;
using Utility;
using System.IO;
using Newtonsoft.Json;
using Domain.Config;
using TencentCloud.Ame.V20190916.Models;
using Tlh.Common;
using Infrastructure.Cache;

namespace Application.App
{
    public class UserApplication
    {
        public IUserRepository userRepository { get; set; }
        public IGeTuiRelationRepository geTuiRelationRepository { get; set; }
        public ITaskTakeRepository taseTakeRepository { get; set; }
        public IWalletRepository walletRepository { get; set; }
        public UserService userService { get; set; }
        public SmsService smsService { get; set; }
        public IEFUnitOfWork efUnitOfWork { get; set; }
        public IConfiguration Configuration { get; set; }
        public FeeService feeService { get; set; }
        public IMService iMService { get; set; }
        public IInComeWalletLogRepository inComeWalletLogRepository { get; set; }

        public bool SendSms(string Phone, SmsCodeType smsCodeType, string Ip)
        {
            return smsService.SendSms(Phone, smsCodeType, Ip);
        }


        public UserLoginOutput UserRegister(RegisterInput registerInput)
        {
            var config = new MapperConfiguration(cfg =>
            {
                cfg.CreateMap<RegisterInput, LoginLogAggregate>();

                cfg.SourceMemberNamingConvention = new PascalCaseNamingConvention();
                cfg.DestinationMemberNamingConvention = new LowerUnderscoreNamingConvention();
            });
            var mapper = config.CreateMapper();
            LoginLogAggregate loginLog = mapper.Map<LoginLogAggregate>(registerInput);

            var temp = userService.UserRegister(registerInput.Phone, registerInput.RegisterToken, registerInput.InviteCode, loginLog);

            UserLoginOutput userLoginOutput = new UserLoginOutput();

            userLoginOutput.Token = new JwtSecurityTokenHandler().WriteToken(temp.Item1);
            userLoginOutput.Expiration = temp.Item1.ValidTo;
            userLoginOutput.UserPhone = temp.Item2.Phone;
            //userLoginOutput.NickName = temp.Item2.NickName;
            userLoginOutput.TLevel = temp.Item2.TraderLevel;
            userLoginOutput.ULevel = temp.Item2.UserLevel;
            userLoginOutput.IMUser = iMService.GetIMUser(temp.Item2);
            userLoginOutput.IMUserPwd = iMService.GetIMUserPwd(temp.Item2);
            userLoginOutput.IMUserSig = iMService.GetTXUserSig(temp.Item2);
            userLoginOutput.InviteCode = temp.Item2.InviteCode;

            return userLoginOutput;
        }

        public UserLoginOutput Login(UserLoginInput userLoginInput)
        {
            var config = new MapperConfiguration(cfg =>
            {
                cfg.CreateMap<UserLoginInput, LoginLogAggregate>();

                cfg.SourceMemberNamingConvention = new PascalCaseNamingConvention();
                cfg.DestinationMemberNamingConvention = new LowerUnderscoreNamingConvention();
            });
            var mapper = config.CreateMapper();
            LoginLogAggregate loginLog = mapper.Map<LoginLogAggregate>(userLoginInput);

            var temp = userService.Login(userLoginInput.Phone, userLoginInput.PhoneCode, loginLog);

            UserLoginOutput userLoginOutput = new UserLoginOutput();

            userLoginOutput.Token = new JwtSecurityTokenHandler().WriteToken(temp.Item1);
            userLoginOutput.Expiration = temp.Item1.ValidTo;
            userLoginOutput.UserPhone = temp.Item2.Phone;
            //userLoginOutput.NickName = temp.Item2.NickName;
            userLoginOutput.TLevel = temp.Item2.TraderLevel;
            userLoginOutput.ULevel = temp.Item2.UserLevel;
            userLoginOutput.IMUser = iMService.GetIMUser(temp.Item2);
            userLoginOutput.IMUserPwd = iMService.GetIMUserPwd(temp.Item2);
            userLoginOutput.IMUserSig = iMService.GetTXUserSig(temp.Item2);
            userLoginOutput.InviteCode = temp.Item2.InviteCode;

            var bind = geTuiRelationRepository.Entities.FirstOrDefault(i => i.UserID == temp.Item2.ID);
            userLoginOutput.GeTuiID = bind?.GeTuiID;

            return userLoginOutput;
        }



        public UserLoginOutput Refresh(string authToken)
        {
            var token = userService.Refresh(authToken);
            var uid = token.Claims.FirstOrDefault(i => i.Type == "ID")?.Value;
            var temp = userRepository.GetByKey(int.Parse(uid));

            UserLoginOutput userLoginOutput = new UserLoginOutput();

            userLoginOutput.Token = new JwtSecurityTokenHandler().WriteToken(token);
            userLoginOutput.Expiration = token.ValidTo;
            userLoginOutput.UserPhone = temp.Phone;
            //userLoginOutput.NickName = temp.NickName;
            userLoginOutput.TLevel = temp.TraderLevel;
            userLoginOutput.ULevel = temp.UserLevel;
            userLoginOutput.IMUser = iMService.GetIMUser(temp);
            userLoginOutput.IMUserPwd = iMService.GetIMUserPwd(temp);
            userLoginOutput.IMUserSig = iMService.GetTXUserSig(temp);
            userLoginOutput.InviteCode = temp.InviteCode;

            var bind = geTuiRelationRepository.Entities.FirstOrDefault(i => i.UserID == temp.ID);
            userLoginOutput.GeTuiID = bind?.GeTuiID;

            return userLoginOutput;
        }

        public UserLevelInfoOutput GetUserLevelInfo(int uid)
        {
            UserLevelInfoOutput userLevelInfoOutput = new UserLevelInfoOutput();
            var u = userRepository.GetByKey(uid);

            userLevelInfoOutput.ID = u.ID;
            userLevelInfoOutput.TraderLevel = u.TraderLevel;
            userLevelInfoOutput.UserLevel = u.UserLevel;
            if (u.TraderLevel == TraderLevel.超级商家) userLevelInfoOutput.TraderLevelOutTime = u.TraderLevelLogs.Where(i => i.TraderLevel == TraderLevel.超级商家).OrderByDescending(i => i.OutTime).FirstOrDefault()?.OutTime;
            if (u.UserLevel == UserLevel.任务达人) userLevelInfoOutput.UserLevelOutTime = u.UserLevelLogs.Where(i => i.UserLevel == UserLevel.任务达人).OrderByDescending(i => i.OutTime).FirstOrDefault()?.OutTime;
            return userLevelInfoOutput;
        }



        public bool BindWx(string uid, UserBindWxInput userBindWxInput)
        {
            var u = userRepository.GetByKey(uid);

            userBindWxInput.WeixinAccount = SpecialCharacterUtil.DeleteEmoji(userBindWxInput.WeixinAccount);
            u.WxData = JsonConvert.SerializeObject(userBindWxInput);
            u.NickName = userBindWxInput.WeixinAccount;
            u.WxOpenID = userBindWxInput.WeixinOpenId;
            u.WxUnionID = userBindWxInput.UnionId;

            efUnitOfWork.Commit();
            iMService.UpdateIMUser(u);
            return true;
        }

        public NewFaceInfoOutput NewFaceInfo(string uid, NewFaceInfoInput realNameAuthInput)
        {
            var config = new MapperConfiguration(cfg =>
            {
                cfg.CreateMap<NewFaceInfoInput, RealNameInfo>();

                cfg.SourceMemberNamingConvention = new PascalCaseNamingConvention();
                cfg.DestinationMemberNamingConvention = new LowerUnderscoreNamingConvention();
            });
            var mapper = config.CreateMapper();

            var orderNo = IDGeneratorUtil.GetId().ToString();
            var nonceStr = RandomUtil.GetRandomString(32);
            var version = "1.0.0";
            var uidMd5 = Md5Util.SiginMd5(uid);
            var ticket = FaceIDUtil.GetTicket(uidMd5);
            var sign = FaceIDUtil.MakeTicketSign(uidMd5, nonceStr, ticket, version);
            Console.WriteLine(sign);
            var faceid = FaceIDUtil.GetFaceID(orderNo, realNameAuthInput.RealName, realNameAuthInput.CardNO, uidMd5, sign, version).GetAwaiter().GetResult();

            var num = userRepository.CardUseTime(realNameAuthInput.CardNO);
            if (num >= 3) throw new BizException("操作失败，该身份证被超过3个账号认证！");
            var u = userRepository.GetByKey(int.Parse(uid));

            if (u.RealNameInfo == null)
            {
                RealNameInfo realNameInfo = mapper.Map<RealNameInfo>(realNameAuthInput);
                //u.RealNameInfo.VideoUrl = url;
                realNameInfo.Status = RealNameStatus.待审核;
                u.RealNameInfo = realNameInfo;
            }
            else
            {
                u.RealNameInfo.CardNO = realNameAuthInput.CardNO;
                u.RealNameInfo.RealName = realNameAuthInput.RealName;
                //u.RealNameInfo.VideoUrl = url;
                //u.RealNameInfo.LivenessType = realNameAuthInput.LivenessType;
                u.RealNameInfo.Status = RealNameStatus.待审核;
            }

            efUnitOfWork.Commit();

            return new NewFaceInfoOutput { Version = version, FaceID = faceid, Sign = sign, NonceStr = nonceStr, OrderNo = orderNo,UserID= uidMd5 };
        }

        public bool GetFaceResult(string uid, string order_no, string version = "1.0.0")
        {
            var nonceStr = RandomUtil.GetRandomString(32);
            var ticket = FaceIDUtil.GetTicket(uid, "SIGN");
            var sign = FaceIDUtil.MakeResultSign(order_no, version, ticket, nonceStr);
           
            var u = userRepository.GetByKey(int.Parse(uid));
            try
            {
                var result = FaceIDUtil.GetFaceResult(order_no, nonceStr, sign, version).GetAwaiter().GetResult();
                u.IsValidRealNameInfo = true;
                u.RealNameInfo.Data = result;
                u.RealNameInfo.Status = RealNameStatus.审核通过;

                efUnitOfWork.Commit();
            }
            catch (BizException e)
            {
                u.RealNameInfo.Data = (string)e.Data["data"];
                u.RealNameInfo.Status = RealNameStatus.审核未通过;

                efUnitOfWork.Commit();
                throw;
            }
           
            return true;
        }

        public RealNameInfo GetRealNameAuthInfo(int v)
        {
            var u = userRepository.GetByKey(v);

            return u.RealNameInfo;
        }
        public UserInfoOutput GetUserInfo(int uid)
        {
            var config = new MapperConfiguration(cfg =>
            {
                cfg.CreateMap<UserInfoAggregate, UserInfoOutput>();

                cfg.SourceMemberNamingConvention = new PascalCaseNamingConvention();
                cfg.DestinationMemberNamingConvention = new LowerUnderscoreNamingConvention();
            });
            var mapper = config.CreateMapper();
            var u = userRepository.GetByKey(uid);


            return mapper.Map<UserInfoOutput>(u);
        }
        public bool SetUserInfo(int uid, UserInfoInput userInfoInput)
        {
            var u = userRepository.GetByKey(uid);

            u.NickName = userInfoInput.NickName;
            u.HeadImg = userInfoInput.HeadImg;
            var r = efUnitOfWork.Commit() > 0;
            iMService.UpdateIMUser(u);

            return r;
        }

        public int PayUpLevelByTrader(int uid, int month)
        {
            int fee = SystemConfig.GetConfigByTime<int>("系统配置", $"等级.超级商人.{month}个月", TimeSpan.FromDays(1));

            var wallet = walletRepository.Entities.FirstOrDefault(i => i.UserID == uid);

            var chazhi = wallet.ChargeNeedPay(fee);

            if (chazhi > 0) return chazhi;

            wallet.UT = DateTime.Now;

            //升级
            wallet.AddDomainEvent(new PayUpLevelByTraderEvent()
            {
                CT = DateTime.Now,
                Month = month,
                PayID = 0,
                PayMoney = 0,
                UserID = uid
            });

            //var log = userService.PayUpLevelByTrader(uid, month,0,fee);

            ////上线收益计算
            //var r2 = feeService.HandleUserUpSuperorReward(uid, fee);// r.PayMoney

            efUnitOfWork.Commit();

            return 0;
        }


        public int PayUpLevelByUser(int uid, int month)
        {
            int fee = SystemConfig.GetConfigByTime<int>("系统配置", $"等级.任务达人.{month}个月", TimeSpan.FromDays(1));

            var wallet = walletRepository.Entities.FirstOrDefault(i => i.UserID == uid);

            var chazhi = wallet.ChargeNeedPay(fee);

            if (chazhi > 0) return chazhi;

            wallet.UT = DateTime.Now;

            //升级
            wallet.AddDomainEvent(new PayUpLevelByUserEvent()
            {
                CT = DateTime.Now,
                Month = month,
                PayID = 0,
                PayMoney = 0,
                UserID = uid
            });

            //var log = userService.PayUpLevelByTrader(uid, month,0,fee);

            ////上线收益计算
            //var r2 = feeService.HandleUserUpSuperorReward(uid, fee);// r.PayMoney

            efUnitOfWork.Commit();

            return 0;
        }


        public object GetIMInfo(string iMUser)
        {
            var phone = iMService.GetIMUserPhone(iMUser);

            var u = userRepository.Entities.FirstOrDefault(i=>i.Phone== phone);


            return new {u.NickName,u.HeadImg,u.Phone,u.ID };
        }
    }
}
